package cn.wolfcode.crm.shiro;

import cn.wolfcode.crm.domain.Employee;
import cn.wolfcode.crm.mapper.EmployeeMapper;
import cn.wolfcode.crm.mapper.PermissionMapper;
import cn.wolfcode.crm.mapper.RoleMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * Created by GG on 2020/3/20.
 * 自定义数据源的处理*/
@Component("crmRealm")
public  class CRMRealm extends AuthorizingRealm {
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private RoleMapper roleMapper;

    //从spring容器中找到credentialsMatcher(shiro.xml文件中),注入属性
    @Autowired
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(credentialsMatcher);
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取登录的用户名(令牌的用户名)
        String principal = (String) token.getPrincipal();
        //查询数据库是否有该账号,如果有就返回相关信息
        //暂时提供假数据(数据库中有真实数据)
        /*String username="admin";
        String password ="1";
        if (principal.equals(username)){
            //info中必须包含密码信息,提供给其他组件进行密码匹配,(realName)是标志当前的信息是从哪个数据源查出来的,一般是类名
            return new SimpleAuthenticationInfo(username,password,"CRMRealm");
        }*/
        //改为真实数据,从数据库中拿,首先要员工属性
        Employee employee = employeeMapper.selectByName(principal);
        //查询数据库中是否有该账户,如果有就返回相关信息
        if (employee != null) {
            //info中必须包含密码的信息,提供给其他组件进行密码匹配
            //realmName是标志单钱的信息是从哪个数据源查出来的,现在其实用不上,跟类名对应就可以了
            //第一个参数是subject里面的额身份信息,希望以后获取到的员工信息,所以这里传整个employee对象
            //把employee.getName()改为employee
            return new SimpleAuthenticationInfo(employee, employee.getPassword(),
                    ByteSource.Util.bytes(employee.getName()), "crmRealm");
        }
        //如果没有返回null
        return null;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("============================================");
        //权限认证,使用接口实现类SimpleAuthorizationInfo
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();
        //获取当前登录用户
        Employee employee = (Employee) subject.getPrincipal();
        //判断是否是超管
        if (employee.isAdmin()) {
            info.addRole("admin");//约定,以后的判断也用整个名称
            info.addStringPermission("*:*");//获取全部权限
        } else {

            //当前用户有哪些角色编码,有哪些权限表达式,全部查询出来后添加到info对象中
            List<String> roles = roleMapper.selectBySnEmpId(employee.getId());
            info.addRoles(roles);
            List<String> permissions = permissionMapper.selectByEmpId(employee.getId());
            info.addStringPermissions(permissions);

        }
        return info;
    }
}


